#include "Smartphone.h"
#include <QDebug>
#include <QMetaType>
#include <QDir>

#ifdef __cplusplus
extern "C"{
#endif
static void smartphone_log_func(SmartphoneLogLevel level, const char *fmt, va_list args);
static void smartphone_callback(SmartphoneCallbackParam *param);

#ifdef __cplusplus
}
#endif



Smartphone::Smartphone(QObject *parent) : QObject(parent)
{

    qRegisterMetaType<SmartphoneState>("SmartphoneState");//注册PVCI_CAN_OBJ类型
    incomingWidget = new IncomingWidget();
    callWidget = new CallWidget();
    timer = new QTimer(this);
    connect(this->timer, SIGNAL(timeout()), this, SLOT(slotTimeOut()));
    timer->start(20);

    smartphone_init(smartphone_callback, smartphone_log_func);
    this->setNativeWindowId((long)callWidget->getDisplay()->winId());
    this->setNativePreviewWindowId((long)callWidget->getDisplayPreview()->winId());

    connect(this, SIGNAL(signalCallStateChanged(SmartphoneState,long,QString,QString,QString)), this,
            SLOT(slotCallStateChanged(SmartphoneState,long,QString,QString,QString)));

    /*******设置铃声*********/
    QString currentPath = QDir::currentPath();
    QString ringPath = currentPath.append("/rings/ring.wav");
    setRing(ringPath);

    /******设置编解码器插件**********/
    QString pluginsPath = QDir::currentPath().append("/plugins");
    reloadMsPlugins(pluginsPath);

    QString picturePath = QDir::currentPath().append("/images/static.jpg");

    setStaticPicture(picturePath);
    QString recordPath = QDir::currentPath().append("/record/test.mkv");
    setRecordPath(recordPath);
}
Smartphone::~Smartphone()
{
    delete incomingWidget;
    delete callWidget;
    timer->stop();
    delete timer;
}

Smartphone *Smartphone::getInstance()
{
    static Smartphone instance;
    return &instance;
}
void Smartphone::slotTimeOut()
{
    smartphone_iterate();
}

void Smartphone::setNativeWindowId(long id)
{
    smartphone_set_native_window_id((void*)id);
}
void Smartphone::setNativePreviewWindowId(long id)
{
    smartphone_set_native_preview_window_id((void*)id);
}
void Smartphone::setStaticPicture(QString picture)
{
    QByteArray ba_picture = picture.toLatin1();
    smartphone_set_static_picture(ba_picture.data());
}
void Smartphone::setStaticPictureFps(int fps)
{
    smartphone_set_static_picture_fps(fps);
}

static void smartphone_callback(SmartphoneCallbackParam *param)
{
    Smartphone::getInstance()->SmartphoneCallback(param);
}
static void smartphone_log_func(SmartphoneLogLevel level, const char *fmt, va_list args)
{
    char str[4096];
    vsnprintf(str, sizeof(str) - 1, fmt, args);
    str[sizeof(str) - 1] = '\0';
    qDebug("%s\n",str);
}
void Smartphone::SmartphoneCallback(SmartphoneCallbackParam *param)
{
    switch(param->state)
    {
    case SmartphoneRegistrationNone:
    case SmartphoneRegistrationProgress:
    case SmartphoneRegistrationOk:
    case SmartphoneRegistrationCleared:
    case SmartphoneRegistrationFailed:
    {
        RegistrationStateInfo *regInfo;
        QString proxy;
        QString message;
        regInfo = (RegistrationStateInfo *)param->data;
        proxy =  QString(regInfo->proxy);
        message = QString(regInfo->message);
        emit signalRegistrationStateChanged(param->state, proxy, message);
        break;
    }
    case SmartphoneCallIncomingReceived:
    case SmartphoneCallIdle:
    case SmartphoneCallOutgoingInit:
    case SmartphoneCallOutgoingProgress:
    case SmartphoneCallOutgoingRinging:
    case SmartphoneCallOutgoingEarlyMedia:
    case SmartphoneCallConnected:
    case SmartphoneCallStreamsRunning:
    case SmartphoneCallPausing:
    case SmartphoneCallPaused:
    case SmartphoneCallResuming:
    case SmartphoneCallRefered:
    case SmartphoneCallError:
    case SmartphoneallEnd:
    case SmartphoneCallPausedByRemote:
    case SmartphoneCallUpdatedByRemote:
    case SmartphoneCallIncomingEarlyMedia:
    case SmartphoneCallUpdating:
    case SmartphoneCallReleased:
    case SmartphoneCallEarlyUpdatedByRemote:
    case SmartphoneCallEarlyUpdating:
    {
        CallStateInfo *callInfo = (CallStateInfo*)param->data;
        long callid = callInfo->callid;
        QString username(callInfo->username);
        QString dispname(callInfo->dispname);
        QString message(callInfo->message);
        emit signalCallStateChanged(param->state, callid, username, dispname, message);
        break;
    }

    default:
        break;
    }
}

void Smartphone::slotCallStateChanged(SmartphoneState state, long callid, QString username, QString dispname, QString message)
{
    switch(state)
    {
    case SmartphoneCallIncomingReceived:
        if(getCallsNb() > 1) return;
        setCurrentCallid(callid);
        incomingWidget->show();
        incomingWidget->setDispname(dispname);
        incomingWidget->setUsername(username);
        qDebug()<<message<<endl;
        break;
    case SmartphoneCallOutgoingInit:
        callWidget->show();
        setCurrentCallid(callid);
        break;
    case SmartphoneCallStreamsRunning:
        callWidget->show();
        break;
    case SmartphoneallEnd:
        incomingWidget->hide();
        callWidget->hide();
    break;
    case SmartphoneCallReleased:

        break;
    default:
        break;
    }
}

void Smartphone::setCurrentCallid(long callid)
{
    this->currentCallid = callid;
}
long Smartphone::getCurrentCallid()
{
    return this->currentCallid;
}


void Smartphone::call(QString identity, MediaType mt, MediaDirection mdAudio, MediaDirection mdVideo)
{
    if(identity.isNull() || identity.isEmpty())
    {
        qDebug()<<"identity is invalid";
        return;
    }
    QByteArray ba_identity = identity.toLatin1();
    smartphone_call(ba_identity.data(), mt, mdAudio, mdVideo);
}
void Smartphone::startRecording()
{
    smartphone_start_recording();
}
void Smartphone::stopRecording()
{
    smartphone_stop_recording();
}
void Smartphone::takePreviewSnapshot(long callid, QString path)
{
    QByteArray ba_path = path.toLatin1();
    smartphone_take_preview_snapshot(callid, ba_path.data());
}

void Smartphone::answer(long callid, MediaType mt, MediaDirection mdAudio, MediaDirection mdVideo)
{
    smartphone_answer(callid, mt, mdAudio, mdVideo);
}
void Smartphone::terminate(long callid)
{
    smartphone_terminate(callid);
}

int Smartphone::login(QString server_addr, SmartphoneTransportType portType,
                      QString dispname, QString username, QString passwd, int expires)
{
    const char *ch_server;
    const char *ch_dispname;
    const char *ch_username;
    const char *ch_passwd;

    if(server_addr.isNull() || server_addr.isEmpty())
    {
        qDebug()<<"server address is invalid!";
        return -1;
    }
    QByteArray arr_server = server_addr.toLatin1();
    ch_server = arr_server.data();

    QByteArray arr_dispname = dispname.toLatin1();
    ch_dispname = arr_dispname.data();

    QByteArray arr_username = username.toLatin1();
    ch_username = arr_username.data();

    QByteArray arr_passwd = passwd.toLatin1();
    ch_passwd = arr_passwd.data();
    smartphone_register(ch_server, portType, ch_dispname,
                        ch_username, ch_passwd, expires);

    return 0;
}
void Smartphone::logout()
{
    smartphone_unregister();
}
void Smartphone::refreshRegisters()
{
    smartphone_refresh_registers();
}
int Smartphone::getCallsNb()
{
    return smartphone_get_calls_nb();
}

void Smartphone::setRing(QString ring)
{
    const char *ch_ring;
    QByteArray arr_ring = ring.toLatin1();
    ch_ring = arr_ring.data();
    smartphone_set_ring(ch_ring);

}
void Smartphone::reloadMsPlugins(const QString path)
{
    const char *ch_path;
    QByteArray arr_path = path.toLatin1();
    ch_path = arr_path.data();
    smartphone_reload_ms_plugins(ch_path);
}
void Smartphone::setRecordPath(QString path)
{
    QByteArray ba_path = path.toLatin1();
    smartphone_set_record_file(ba_path.data());

}

void Smartphone::sendInfo(QString info, long callid)
{
    const char *ch_info;
    QByteArray arr_info = info.toLatin1();
    ch_info = arr_info.data();
    smartphone_send_info(ch_info, callid);
}
QVector<QString> Smartphone::getVideoDevices()
{
    QVector<QString> vector;
    int size = smartphone_get_video_device_size();
    for(int i = 0; i < size; i++)
    {
        QString str = QString(QLatin1String(smartphone_get_video_device_name(i)));
        vector.append(str);
    }
    return vector;
}
void Smartphone::setVideoDevice(int id)
{
    smartphone_set_video_device(id);
}

QVector<QString> Smartphone::getCodecs(CodecType ct)
{
    QVector<QString> vector;
    int size = smartphone_get_codec_size(ct);
    for(int i = 0; i < size; i++)
    {
        QString str = QString(QLatin1String(smartphone_get_codec_name(CodecTypeAudio, i)));
        vector.append(str);
    }
    return vector;
}
void Smartphone::enableCodec(CodecType ct, int id, bool enabled)
{
    smartphone_enable_codec(ct, id, enabled);
}
long Smartphone::createLocalPlayer(long windowid){
    return smartphone_create_local_player(windowid);
}
void Smartphone::destroyPlayer(long player){
    smartphone_player_destroy(player);
}
void Smartphone::openPlayer(long player, QString filename)
{
    QByteArray arr = filename.toLatin1();
    smartphone_player_open(player, arr.data());
}
void Smartphone::closePlayer(long player){
    smartphone_player_close(player);
}
void Smartphone::startPlayer(long player){
    smartphone_player_start(player);
}

void Smartphone::pausePlayer(long player){
    smartphone_player_pause(player);

}
